package entrevista;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;

public class Organizacion {

	
	
	//root THE BOSS
	Node root;
	
	public Organizacion(Villano theBoss) throws Exception {
		//
		
		if (theBoss == null){
			throw new Exception("The boss is empty: Organization Constructor");
		}
		else{
			root = new Node(theBoss);
		}
		
	}
	
	
	//To call this recursive funtion current must be equal to root. Villain level starts in 0
	public Node lookForVillain(Villano villain, Node current, int villainLevel){
		
		if (current.getData().getName() == villain.getName()){
			return current;
		}
		else{
			for (Node n : current.getChildren()){
				villainLevel++;
				Node found = lookForVillain(villain, n,villainLevel);
				if ( found != null){
					return found;
				}
				
			}
			
			return null;
		}
		
	}
	
	//We supposed the villain is correctly inicializated 
	public void insertVillain(Villano villain){
		int level = 0;
			
		Node bossNode = lookForVillain(villain.getActualBoss(), root, level);
		
		Node newVillain = new Node(villain);
		
		bossNode.getChildren().add(newVillain);
		
	}
	
	//Current level is 0 and currentNode is root when this function is call. The level is saved in level variable
	public void getLevel(int currentLevel, int desiredLevel, List<Node> level, Node currentNode){
		
		if(currentLevel == desiredLevel){
			
				level.add(currentNode);
			
		}
		else{
			currentLevel++;
			
			for ( Node node : currentNode.getChildren()){
				
				getLevel(currentLevel, desiredLevel, level, node);
			}	
		}
		
	}
	
	public void memberGoToJail(Villano villain) throws Exception{
		//look for the level of the boss
		int bossLevel=0;
		Node nodeVillain = lookForVillain(villain.getActualBoss(), root, bossLevel);
		
		//Get all the villain at boss level
		List<Node> villainsAtLevel = new ArrayList<Node>();
		
		
		getLevel(0, bossLevel , villainsAtLevel, root);
		
		
		if( villainsAtLevel.size() != 0){
			//look for the older of the level
			Node older = villainsAtLevel.get(0);
			
			for( Node n : villainsAtLevel){
				if(older.getData().getRegisterIntoMafia() < n.getData().getRegisterIntoMafia()){
					older = n;
				}
			}
			//move subordinate to new one
			for (Node node : nodeVillain.getChildren()){
				node.getData().getOldBosses().add(node.getData().getActualBoss());
				node.getData().setActualBoss(older.getData());
				older.getChildren().add(node);
			}
			
			
		}
		else{
			
			int villainLevel =0;
			//look for the older of the subordinates
			Node villaiNode =lookForVillain(villain, root, villainLevel);
			Node older = villaiNode.getChildren().get(0);
			for( Node n : villaiNode.getChildren()){
				if(older.getData().getRegisterIntoMafia() < n.getData().getRegisterIntoMafia()){
					older = n;
				}
			}
			
			
			//----promote the older of the subordinates
			villaiNode.getChildren().remove(older);
			//looking for the boss of current villain
			Node villainBoss = lookForVillain(villain.getActualBoss(), root, villainLevel);
			villainBoss.getChildren().add(older); 
			//update actual boss
			older.getData().setActualBoss(villainBoss.getData());
			older.getData().getOldBosses().add(villaiNode.getData());
			
			//add new subordinates (villain going to jail old subordinates) to promoted member		
			
			for(Node n: villaiNode.getChildren())
			{
				older.getChildren().add(n);
				//update cbosses
				n.getData().setActualBoss(older.getData());
				n.getData().getOldBosses().add(villaiNode.getData());
			}
			
		}
		
	}
	
	//TODO 
	public void membersCameFromJail(Villano villainFromJail){
		
		//Create a node for the
		
		//Who was his old boss
		Villano hisOldBoss = villainFromJail.getActualBoss();
		
		//Set the actual boss
		villainFromJail.setActualBoss(hisOldBoss);
		
		//Look for the node of his old Boss
		int levelOldBoss = 0;
		Node oldBossNode = lookForVillain(hisOldBoss, root, levelOldBoss);

		List<Node> tempNewMembers = new ArrayList<Node>();
		
		int villainLevel = 0;
		
		//For each subordinate of the villainFromJail
		for(Node children: oldBossNode.getChildren()){
			
			//Look for him in the structure
			Node foundNode = lookForVillain(children.getData(), root, villainLevel);
			
			//if found it
			if (foundNode != null){
				//add to a temp list
				tempNewMembers.add(foundNode);
				//delete from structure
				foundNode.getChildren().remove(foundNode);
			}
			
		}
		
		
		
				
		//Insert the villainFomJail to his members
		oldBossNode.getChildren().add(new Node(villainFromJail));
		
		
		
		
		
	}
	//method to look for numbers of subordinates
	public void getNumberOfSubordinate(Node villano, int numSubordinates){
	
		
			numSubordinates += villano.getChildren().size();
			for(Node n : villano.getChildren()){
				getNumberOfSubordinate(n, numSubordinates);
			}
		

	}


	public Node getRoot() {
		return root;
	}


	public void setRoot(Node root) {
		this.root = root;
	}
	
	

}
